package com.itany.jdbc.jdbc;


import com.itany.jdbc.execption.DataAccessExecption;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 陈华旺
 * @version 1.0
 * @date 2023年10月25日 16:56
 * @Description TODO
 */
public class JDBCTemplate {

    private void setParams(PreparedStatement ps,Object ...args) throws SQLException {
//        setObject 方法对于 string int double 的参数设置效率较低
        for (int i = 0; i < args.length; i++) {
            if( args[i] instanceof String ){
                ps.setString(i+1,(String)args[i]);
            }else if( args[i] instanceof Integer ){
                ps.setInt(i+1,(int)args[i]);
            }else if( args[i] instanceof Double ){
                ps.setDouble(i+1,(double)args[i]);
            }else{
                ps.setObject(i+1,args[i]);
            }
        }
    }

    public void update(String sql,Object ...args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);
//            使用专门的 参数设置方法，完成参数设置
            if(null != args) this.setParams(ps,args);
            ps.executeUpdate();
        } catch (SQLException e){
            throw new DataAccessExecption("JDBCTemplate.update:"+e.getMessage());
        } finally {
            JDBCUtil.close(ps,null);
        }
    }

//    添加返回主键 - 不做批处理
    public void insertReturnPK(PreparedStatementCreator psc,KeyHoder keyHoder){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
//            基于公开接口获取 PreparedStatement sql执行对象
//            具体的 对象 配置（sql，参数，批处理） 都通过该接口的实现类进行实现
            ps = psc.createPreparedStatement(conn);
            ps.executeUpdate();
//            获取主键 - 按照联合主键处理
            rs = ps.getGeneratedKeys();
//            构建集合存储主键
            List<Object> keys = new ArrayList<>();
            if(rs.next()){
//              获取查询结果表的元信息
                ResultSetMetaData rsmd = rs.getMetaData();
                int count = rsmd.getColumnCount();
                for (int i = 1; i <= count; i++) {
                    keys.add( rs.getObject(i) );
                }
            }
            keyHoder.setKeyList( keys );
        } catch (SQLException e) {
            throw new DataAccessExecption("JDBCTemplate.update:"+e.getMessage());
        } finally {
            JDBCUtil.close(ps,rs);
        }
    }

//    自定义扩展方法
    public void update(PreparedStatementCreator psc){
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = JDBCUtil.getConn();
//            基于公开接口获取 PreparedStatement sql执行对象
//            具体的 对象 配置（sql，参数，批处理） 都通过该接口的实现类进行实现
            ps = psc.createPreparedStatement(conn);
            ps.executeUpdate();
        } catch (SQLException e) {
            throw new DataAccessExecption("JDBCTemplate.update:"+e.getMessage());
        } finally {
            JDBCUtil.close(ps,null);
        }
    }

    public <T> List<T> query(String sql,RowMapper<T> rm,Object ...args) {
        List<T> list = null;
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);
            if(null != args) this.setParams(ps,args);
            rs = ps.executeQuery();
            list = rm.mapperRow(rs);
        } catch (SQLException e){
            throw new DataAccessExecption("JDBCTemplate.update:"+e.getMessage());
        } finally {
            JDBCUtil.close(ps,rs);
        }
        return list;
    }

    public <T> T queryOne(String sql,RowMapper<T> rm,Object ...args) {
        List<T> list = this.query(sql,rm,args);
        return list.isEmpty() ? null : list.get(0);
    }

}
